package com.dapeng.jackson.abstracts;

import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;

import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * @BelongProject study
 * @BelongPackage com.dapeng.jackson
 * @Description TODO
 * @ClassName BaseJKAnnotationDeSerializer
 * @Author xupenghong
 * @Date 2024/9/13 15:52
 * @Version 1.0.0
 */

/**
 * @param <A>         自定义反序列化注解
 * @param <FieldType> 处理的反序列化的字段类型
 */
public abstract class BaseJKAnnotationDeSerializer<A extends Annotation, FieldType> extends JsonDeserializer<FieldType> implements ContextualDeserializer {

    /**
     * 字段标记的注解
     */
    protected A annotation;

    /**
     * 反序列化的字段类型
     */
    protected Class<?> fieldClass;

    /**
     * 反序列化的字段名
     */
    protected String fieldName;

    /**
     * 动态决定序列化的方式，以及获取序列化的上下文，比如要序列化的字段的信息等等
     */
    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext prov, BeanProperty property) throws JsonMappingException {
        // 子类获取父亲标记的泛型参数
        Type superclass = getClass().getGenericSuperclass();
        Class<A> acls = null;
        if (superclass instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) superclass;
            Type actualTypeArgument = parameterizedType.getActualTypeArguments()[0];
            acls = (Class<A>) actualTypeArgument;
        }

        this.fieldClass = property.getType().getRawClass();
        this.fieldName = property.getName();

        annotation = property.getAnnotation(acls);
        if (annotation == null || !isFilterDeserializer(property)) {
            return prov.findContextualValueDeserializer(property.getType(), property);
        }

        return this;
    }

    /**
     * 判断是否需要使用此反序列化器
     */
    protected boolean isFilterDeserializer(BeanProperty property) {
        return true;
    }
}
